import 'dart:typed_data';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_nfc_kit/flutter_nfc_kit.dart';
import 'package:ndef/ndef.dart' as ndef;
import 'mock_platform_test.dart';

void main() {
  TestWidgetsFlutterBinding.ensureInitialized();
  
  group('NFC Integration Tests', () {
    setUp(() {
      MockNfcPlatform.setupMockMethodCallHandler();
      MockNfcTestHelper.resetToNormalState();
    });

    tearDown(() {
      MockNfcPlatform.tearDown();
    });

    group('Complete NFC Session Workflow', () {
      test('should complete full NDEF read/write session', () async {
        // 设置带有NDEF功能的标签
        final mockTag = MockNfcTestHelper.createIso7816Tag(
          ndefAvailable: true,
          ndefCapacity: 8192,
        );
        MockNfcPlatform.setMockTag(mockTag);

        // 设置初始NDEF数据
        final initialRecords = [
          MockNfcTestHelper.createNdefTextRecord('Hello World'),
        ];
        MockNfcPlatform.setMockNdefRecords(initialRecords);

        // 1. 检查NFC可用性
        final availability = await FlutterNfcKit.nfcAvailability;
        expect(availability, NFCAvailability.available);

        // 2. 轮询标签
        final tag = await FlutterNfcKit.poll();
        expect(tag.type, NFCTagType.iso7816);
        expect(tag.ndefAvailable, true);
        expect(tag.ndefCapacity, 8192);

        // 3. 读取NDEF记录
        final readRecords = await FlutterNfcKit.readNDEFRawRecords();
        expect(readRecords.length, 1);
        expect(readRecords[0].typeNameFormat.name, 'nfcWellKnown');

        // 4. 写入新的NDEF记录
        final newRecords = [
          NDEFRawRecord(
            '',
            '0265656E4E657720546578742044617461', // "en" + "New Text Data"
            '54', // Text record type
            ndef.TypeNameFormat.nfcWellKnown,
          ),
          NDEFRawRecord(
            '',
            '0068747470733A2F2F6578616D706C652E636F6D', // "https://example.com"
            '55', // URI record type
            ndef.TypeNameFormat.nfcWellKnown,
          ),
        ];
        await FlutterNfcKit.writeNDEFRawRecords(newRecords);

        // 5. 验证写入的数据
        final verifyRecords = await FlutterNfcKit.readNDEFRawRecords();
        expect(verifyRecords.length, 2);
        expect(verifyRecords[0].type, '54');
        expect(verifyRecords[1].type, '55');

        // 6. 结束会话
        await FlutterNfcKit.finish();
        expect(MockNfcPlatform.isSessionActive, false);
      });

      test('should complete full MIFARE Classic workflow', () async {
        // 设置MIFARE Classic标签
        final mockTag = MockNfcTestHelper.createMifareClassicTag(
          type: 'MIFARE_CLASSIC_1K',
          blockCount: 64,
          sectorCount: 16,
        );
        MockNfcPlatform.setMockTag(mockTag);

        // 1. 轮询标签
        final tag = await FlutterNfcKit.poll();
        expect(tag.type, NFCTagType.mifare_classic);
        expect(tag.mifareInfo?.type, 'MIFARE_CLASSIC_1K');
        expect(tag.mifareInfo?.blockCount, 64);

        // 2. 认证扇区1
        MockNfcPlatform.authenticateSector(1, true);
        final authResult = await FlutterNfcKit.authenticateSector<String>(
          1,
          keyA: TestMifareKeys.defaultKey,
        );
        expect(authResult, true);

        // 3. 读取块4（扇区1的第一个块）
        final testData = Uint8List.fromList([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
                                           0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10]);
        MockNfcPlatform.setBlockData(4, testData);
        
        final readData = await FlutterNfcKit.readBlock(4);
        expect(readData, testData);

        // 4. 写入新数据到块5
        final newData = Uint8List.fromList([0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88,
                                          0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00]);
        await FlutterNfcKit.writeBlock<Uint8List>(5, newData);

        // 5. 验证写入的数据
        final verifyData = await FlutterNfcKit.readBlock(5);
        expect(verifyData, newData);

        // 6. 读取整个扇区
        final sectorData = await FlutterNfcKit.readSector(1);
        expect(sectorData.length, 64);

        // 7. 结束会话
        await FlutterNfcKit.finish();
      });

      test('should handle ISO 7816 APDU communication', () async {
        // 设置ISO 7816标签
        final mockTag = MockNfcTestHelper.createIso7816Tag();
        MockNfcPlatform.setMockTag(mockTag);

        // 1. 轮询标签
        final tag = await FlutterNfcKit.poll();
        expect(tag.type, NFCTagType.iso7816);

        // 2. 发送SELECT APPLICATION命令
        final selectResponse = await FlutterNfcKit.transceive<String>(
          TestApduCommands.selectApplicationCmd,
        );
        expect(selectResponse, TestApduCommands.successResponse);

        // 3. 使用字节数组发送命令
        final selectBytes = await FlutterNfcKit.transceive<Uint8List>(
          TestApduCommands.selectApplicationBytes,
        );
        expect(selectBytes, TestApduCommands.successResponseBytes);

        // 4. 使用自定义超时发送命令
        final customTimeoutResponse = await FlutterNfcKit.transceive<String>(
          TestApduCommands.readRecordCmd,
          timeout: const Duration(seconds: 10),
        );
        expect(customTimeoutResponse, TestApduCommands.successResponse);

        // 5. 结束会话
        await FlutterNfcKit.finish();
      });
    });

    group('Error Scenarios', () {
      test('should handle NFC not available', () async {
        MockNfcPlatform.setNfcAvailability('disabled');
        
        final availability = await FlutterNfcKit.nfcAvailability;
        expect(availability, NFCAvailability.disabled);
      });

      test('should handle NFC not supported', () async {
        MockNfcPlatform.setNfcAvailability('not_supported');
        
        final availability = await FlutterNfcKit.nfcAvailability;
        expect(availability, NFCAvailability.not_supported);
      });

      test('should handle polling timeout', () async {
        MockNfcTestHelper.setupTimeoutScenario();
        
        expect(
          () async => await FlutterNfcKit.poll(),
          throwsA(predicate((e) => 
            e is PlatformException && 
            e.code == '408' && 
            e.message!.contains('timeout')
          )),
        );
      });

      test('should handle no tag polled error', () async {
        MockNfcTestHelper.setupErrorScenario('406', 'No tag polled');
        
        expect(
          () async => await FlutterNfcKit.readNDEFRawRecords(),
          throwsA(predicate((e) => 
            e is PlatformException && 
            e.code == '406'
          )),
        );
      });

      test('should handle NDEF not supported error', () async {
        MockNfcTestHelper.setupErrorScenario('405', 'NDEF not supported on current tag');
        
        expect(
          () async => await FlutterNfcKit.readNDEFRawRecords(),
          throwsA(predicate((e) => 
            e is PlatformException && 
            e.code == '405'
          )),
        );
      });

      test('should handle MIFARE authentication failure', () async {
        final mockTag = MockNfcTestHelper.createMifareClassicTag();
        MockNfcPlatform.setMockTag(mockTag);
        
        await FlutterNfcKit.poll();
        
        // 设置认证失败
        MockNfcPlatform.authenticateSector(1, false);
        
        final authResult = await FlutterNfcKit.authenticateSector<String>(
          1,
          keyA: 'WRONGKEY123',
        );
        
        expect(authResult, false);
        
        await FlutterNfcKit.finish();
      });

      test('should handle session management errors', () async {
        // 尝试在没有活动会话时进行操作
        expect(
          () async => await FlutterNfcKit.readNDEFRawRecords(),
          throwsA(predicate((e) => 
            e is PlatformException && 
            e.code == '406'
          )),
        );

        expect(
          () async => await FlutterNfcKit.transceive<String>('00A4040007A0000002471001'),
          throwsA(predicate((e) => 
            e is PlatformException && 
            e.code == '406'
          )),
        );
      });
    });

    group('Edge Cases', () {
      test('should handle empty NDEF records', () async {
        final mockTag = MockNfcTestHelper.createIso7816Tag();
        MockNfcPlatform.setMockTag(mockTag);
        MockNfcPlatform.setMockNdefRecords([]);

        await FlutterNfcKit.poll();
        
        final records = await FlutterNfcKit.readNDEFRawRecords();
        expect(records.isEmpty, true);
        
        await FlutterNfcKit.finish();
      });

      test('should handle large NDEF payload', () async {
        final mockTag = MockNfcTestHelper.createIso7816Tag(ndefCapacity: 8192);
        MockNfcPlatform.setMockTag(mockTag);

        // 创建大型NDEF载荷
        final largePayload = List.generate(1000, (i) => (i % 256).toRadixString(16).padLeft(2, '0')).join('');
        final largeRecord = {
          'identifier': '',
          'payload': largePayload,
          'type': '54',
          'typeNameFormat': 'nfcWellKnown',
        };
        MockNfcPlatform.setMockNdefRecords([largeRecord]);

        await FlutterNfcKit.poll();
        
        final records = await FlutterNfcKit.readNDEFRawRecords();
        expect(records.length, 1);
        expect(records[0].payload.length, largePayload.length);
        
        await FlutterNfcKit.finish();
      });

      test('should handle multiple NDEF records', () async {
        final mockTag = MockNfcTestHelper.createIso7816Tag();
        MockNfcPlatform.setMockTag(mockTag);

        final multipleRecords = [
          MockNfcTestHelper.createNdefTextRecord('Text Record 1'),
          MockNfcTestHelper.createNdefTextRecord('Text Record 2'),
          MockNfcTestHelper.createNdefUriRecord('https://example.com'),
          MockNfcTestHelper.createNdefUriRecord('https://flutter.dev'),
        ];
        MockNfcPlatform.setMockNdefRecords(multipleRecords);

        await FlutterNfcKit.poll();
        
        final records = await FlutterNfcKit.readNDEFRawRecords();
        expect(records.length, 4);
        expect(records.where((r) => r.type == '54').length, 2); // 2 text records
        expect(records.where((r) => r.type == '55').length, 2); // 2 URI records
        
        await FlutterNfcKit.finish();
      });

      test('should handle MIFARE sector boundary operations', () async {
        final mockTag = MockNfcTestHelper.createMifareClassicTag();
        MockNfcPlatform.setMockTag(mockTag);

        await FlutterNfcKit.poll();

        // 测试扇区边界（扇区0-15）
        for (int sector = 0; sector < 16; sector++) {
          MockNfcPlatform.authenticateSector(sector, true);
          final authResult = await FlutterNfcKit.authenticateSector<String>(
            sector,
            keyA: TestMifareKeys.defaultKey,
          );
          expect(authResult, true);
        }

        await FlutterNfcKit.finish();
      });

      test('should handle rapid session start/stop cycles', () async {
        final mockTag = MockNfcTestHelper.createIso7816Tag();
        MockNfcPlatform.setMockTag(mockTag);

        // 快速启动和停止多个会话
        for (int i = 0; i < 5; i++) {
          final tag = await FlutterNfcKit.poll();
          expect(tag.type, NFCTagType.iso7816);
          expect(MockNfcPlatform.isSessionActive, true);
          
          await FlutterNfcKit.finish();
          expect(MockNfcPlatform.isSessionActive, false);
        }
      });
    });

    group('Platform-specific Features', () {
      test('should handle iOS-specific methods', () async {
        // 测试iOS重启轮询
        await FlutterNfcKit.iosRestartPolling();
        
        // 测试iOS警告消息设置
        await FlutterNfcKit.setIosAlertMessage('Scan your card');
      });

      test('should handle platform-specific poll options', () async {
        final mockTag = MockNfcTestHelper.createIso7816Tag();
        MockNfcPlatform.setMockTag(mockTag);

        // 测试不同的技术组合
        await FlutterNfcKit.poll(
          readIso14443A: true,
          readIso14443B: false,
          readIso18092: true,
          readIso15693: false,
        );
        await FlutterNfcKit.finish();

        // 测试Android特定选项
        await FlutterNfcKit.poll(
          androidPlatformSound: false,
          androidCheckNDEF: false,
        );
        await FlutterNfcKit.finish();

        // 测试Web USB选项
        await FlutterNfcKit.poll(
          probeWebUSBMagic: true,
        );
        await FlutterNfcKit.finish();
      });

      test('should handle finish with platform-specific options', () async {
        final mockTag = MockNfcTestHelper.createIso7816Tag();
        MockNfcPlatform.setMockTag(mockTag);

        await FlutterNfcKit.poll();

        // 测试iOS消息
        await FlutterNfcKit.finish(
          iosAlertMessage: 'Operation completed successfully',
        );

        await FlutterNfcKit.poll();

        // 测试iOS错误消息
        await FlutterNfcKit.finish(
          iosErrorMessage: 'Operation failed',
        );

        await FlutterNfcKit.poll();

        // 测试WebUSB关闭
        await FlutterNfcKit.finish(
          closeWebUSB: true,
        );
      });
    });

    group('Data Format Handling', () {
      test('should handle hex string data correctly', () async {
        final mockTag = MockNfcTestHelper.createIso7816Tag();
        MockNfcPlatform.setMockTag(mockTag);

        await FlutterNfcKit.poll();

        // 测试十六进制字符串格式
        final hexCommand = '00A4040007A0000002471001';
        final response = await FlutterNfcKit.transceive<String>(hexCommand);
        expect(response, isA<String>());

        await FlutterNfcKit.finish();
      });

      test('should handle byte array data correctly', () async {
        final mockTag = MockNfcTestHelper.createMifareClassicTag();
        MockNfcPlatform.setMockTag(mockTag);

        await FlutterNfcKit.poll();

        MockNfcPlatform.authenticateSector(1, true);
        await FlutterNfcKit.authenticateSector<String>(1, keyA: TestMifareKeys.defaultKey);

        // 测试字节数组格式
        final testData = Uint8List.fromList([0x01, 0x02, 0x03, 0x04]);
        await FlutterNfcKit.writeBlock<Uint8List>(4, testData);

        final readData = await FlutterNfcKit.readBlock(4);
        expect(readData, isA<Uint8List>());

        await FlutterNfcKit.finish();
      });

      test('should handle mixed data types in MIFARE operations', () async {
        final mockTag = MockNfcTestHelper.createMifareClassicTag();
        MockNfcPlatform.setMockTag(mockTag);

        await FlutterNfcKit.poll();

        // 使用字符串密钥认证
        MockNfcPlatform.authenticateSector(1, true);
        final authResult1 = await FlutterNfcKit.authenticateSector<String>(
          1,
          keyA: TestMifareKeys.defaultKey,
        );
        expect(authResult1, true);

        // 使用字节数组密钥认证
        MockNfcPlatform.authenticateSector(2, true);
        final authResult2 = await FlutterNfcKit.authenticateSector<Uint8List>(
          2,
          keyB: TestMifareKeys.mfcKeyBBytes,
        );
        expect(authResult2, true);

        await FlutterNfcKit.finish();
      });
    });
  });
}